package net.jforum.repository;
/**
 * @ author  张洋 jackson.zhang@ericsson.com
 * @ version 创建时间 ：Aug 14, 2010  12:40:36 AM
 * @ description : 
 */
/*
 * Copyright (c) JForum Team
 * All rights reserved.
 * 
 * Redistribution and use in source and binary forms, 
 * with or without modification, are permitted provided 
 * that the following conditions are met:
 * 
 * 1) Redistributions of source code must retain the above 
 * copyright notice, this list of conditions and the 
 * following  disclaimer.
 * 2)  Redistributions in binary form must reproduce the 
 * above copyright notice, this list of conditions and 
 * the following disclaimer in the documentation and/or 
 * other materials provided with the distribution.
 * 3) Neither the name of "Rafael Steil" nor 
 * the names of its contributors may be used to endorse 
 * or promote products derived from this software without 
 * specific prior written permission.
 * 
 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT 
 * HOLDERS AND CONTRIBUTORS "AS IS" AND ANY 
 * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, 
 * BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF 
 * MERCHANTABILITY AND FITNESS FOR A PARTICULAR 
 * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL 
 * THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE 
 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, 
 * EXEMPLARY, OR CONSEQUENTIAL DAMAGES 
 * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF 
 * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, 
 * OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER 
 * CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER 
 * IN CONTRACT, STRICT LIABILITY, OR TORT 
 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN 
 * ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF 
 * ADVISED OF THE POSSIBILITY OF SUCH DAMAGE
 * 
 * This file creation date: 05/04/2004 - 20:11:44
 * The JForum Project
 * http://www.jforum.net
 */

import java.util.ArrayList;
import java.util.Collections;
import java.util.Comparator;
import java.util.HashMap;
import java.util.Iterator;
import java.util.LinkedList;
import java.util.List;
import java.util.Map;

import org.apache.log4j.Logger;

import com.sun.org.apache.bcel.internal.generic.NEW;

import net.jforum.JForumBaseServlet;
import net.jforum.cache.CacheEngine;
import net.jforum.cache.Cacheable;
import net.jforum.dao.DataAccessDriver;
import net.jforum.dao.TopicDAO;
import net.jforum.entities.Topic;
import net.jforum.entities.TopicTypeComparator;
import net.jforum.entities.TopicVirtueStickyComparator;
import net.jforum.util.preferences.ConfigKeys;
import net.jforum.util.preferences.SystemGlobals;

/**
 * Repository for the last n topics for each forum.
 * 
 * @author Rafael Steil
 * @author James Yong
 * @version $Id: TopicRepository.java,v 1.33 2007/09/05 04:00:27 rafaelsteil Exp $
 */
public class TopicRepository implements Cacheable
{
	private static Logger logger = Logger.getLogger(TopicRepository.class);
	
	private static final String FQN = "topics";
	private static final String RECENT = "recent";//(FQN,(recent,LinkedListTopic))
	private static final String FQN_FORUM = FQN + "/byforum";//(FAN_FORUM,(forumId,LinkedList))
	private static final String RELATION = "relation";//(FQN,(relation,map(topicId,forumId)));
	private static final String FQN_LOADED = FQN + "/loaded";//(FQN_LOADED,(forumId,1-0))
	private static final String KU_TOPICS="ku_topic";
	
	
	private static final Comparator TYPE_COMPARATOR = new TopicTypeComparator();
	
	private static final String ALL_CACHE_TOPICS="allCacheTopics"; //虚拟总论坛之用
	private static final String  TOPICS_COUNT="topicCount";//虚拟总论坛之用
	private static final String Ku_TOPICS_COUNT="kuTopicCount";
	private static final String TOPIC_BY_PUBLISH_TIME_CACHE="topicsByPublishTimeCache";
	
	private static CacheEngine cache;
	
  
	
	
	
	
	
	/**
	 * @see net.jforum.cache.Cacheable#setCacheEngine(net.jforum.cache.CacheEngine)
	 */
	public void setCacheEngine(CacheEngine engine)
	{
		cache = engine;
	}
	
	public static boolean isLoaded(int forumId)
	{
		return "1".equals(cache.get(FQN_LOADED, Integer.toString(forumId)));
	}

	/**
	 * Add topic to the FIFO stack
	 * 
	 * @param topic The topic to add to stack recent
	 */
	
	public synchronized static void pushTopic(Topic topic)
	{   
 
		if (SystemGlobals.getBoolValue(ConfigKeys.TOPIC_CACHE_ENABLED)) {
			int limit = SystemGlobals.getIntValue(ConfigKeys.RECENT_TOPICS_CACHE_SIZE);
			
			LinkedList l = (LinkedList)cache.get(FQN, RECENT);
			if (l == null || l.size() == 0) {
				l = new LinkedList(loadMostRecentTopics());
			}
			
			l.remove(topic);
			l.addFirst(topic);
			
			while (l.size() > limit) {
				l.removeLast();
			}
			
			cache.add(FQN, RECENT, l);
		}
	}
    

 
	/**
	 * Get all cached recent topics. 
	 * 
	 */	
	public static List getRecentTopics()
	{   
		
		List l = (List)cache.get(FQN, RECENT);
		
		if (l == null || l.size() == 0
			|| !SystemGlobals.getBoolValue(ConfigKeys.TOPIC_CACHE_ENABLED)) {
			l = loadMostRecentTopics();
		}

		return new ArrayList(l);
	}	
	public static boolean isInRecentCachedTopic(Topic topic){
	    List recentTopics=getRecentTopics();
	    if(recentTopics.contains(topic)) 
	        return true;
	    else return false;    
	}
	
	public static List getRecentTopicsByLimit(int start,int size){
		List recentTopics=getRecentTopics();
		if(recentTopics!=null && recentTopics.size()<start)
			return new ArrayList();
		else{
			return recentTopics.subList(start, start+size);
		}
	}
	
	public static void clearCachedRecentTopics(){
		synchronized(RECENT){
			cache.remove(FQN, RECENT);
		}
	}
    public static int countCachedRecentTopics(){
    	
    	List l=(List)cache.get(FQN,RECENT);
    	return l.size();
    }
	public static List getCachedRecentTopicsByLimit(int start, int limit) {
		List cachedRecentTopics = getRecentTopics();
		int endIndex = start + limit;
		if (start > cachedRecentTopics.size() - 1) {
			return new LinkedList();
		}
		if (endIndex > cachedRecentTopics.size())
			endIndex = cachedRecentTopics.size();

		return cachedRecentTopics.subList(start, endIndex);

	}
 
	/**
	 * Add recent topics to the cache
	 */
	public synchronized static List loadMostRecentTopics()
	{  

		TopicDAO tm = DataAccessDriver.getInstance().newTopicDAO();
		int limit = SystemGlobals.getIntValue(ConfigKeys.RECENT_TOPICS_CACHE_SIZE);
		
		List l = tm.selectRecentTopics(limit);
		cache.add(FQN, RECENT, new LinkedList(l));
		return l;
	}

	/**
	 * Add topics to the cache
	 * 
	 * @param forumId The forum id to which the topics are related
	 * @param topics The topics to add
	 */
	public static void addAll(int forumId, List topics)
	{
		if (SystemGlobals.getBoolValue(ConfigKeys.TOPIC_CACHE_ENABLED)) {
			synchronized (FQN_FORUM) {
				cache.add(FQN_FORUM, Integer.toString(forumId), new LinkedList(topics));
				
				Map m = (Map)cache.get(FQN, RELATION);
				
				if (m == null) {
					m = new HashMap();
				}
				
				Integer fId = new Integer(forumId);
				
				for (Iterator iter = topics.iterator(); iter.hasNext(); ) {
					Topic t = (Topic)iter.next();
					
					m.put(new Integer(t.getId()), fId);
				}
				
				cache.add(FQN, RELATION, m);
				cache.add(FQN_LOADED, Integer.toString(forumId), "1");
			}
		}
	}
	
	/**
	 * Clears the cache
	 * 
	 * @param forumId The forum id to clear the cache
	 */
	public static void clearCache(int forumId) 
	{
		synchronized (FQN_FORUM) {
			cache.add(FQN_FORUM, Integer.toString(forumId), new LinkedList());
			cache.remove(FQN, RELATION);
		}
	}
	
	/**
	 * Adds a new topic to the cache
	 * 
	 * @param topic The topic to add
	 */
	public static void addTopic(Topic topic)
	{
		if (!SystemGlobals.getBoolValue(ConfigKeys.TOPIC_CACHE_ENABLED)) {
			return;
		}
		
		synchronized (FQN_FORUM) {
			String forumId = Integer.toString(topic.getForumId());
			LinkedList list = (LinkedList)cache.get(FQN_FORUM, forumId);
			
			if (list == null) {
				list = new LinkedList();
				list.add(topic);
			}
			else {
				boolean contains = list.contains(topic);
				int topicPerPage = SystemGlobals.getIntValue(ConfigKeys.TOPICS_PER_PAGE);
				int topicsCachedPage=SystemGlobals.getIntValue(ConfigKeys.FORUM_TOPICS_CACHE_PAGE);
				int tpicsCachedCount=topicsCachedPage*topicPerPage;
				// If the cache is full, remove the eldest element
				if (!contains && list.size() + 1 > tpicsCachedCount) {
					list.removeLast();
				}
				else if (contains) {
					list.remove(topic);
				}
				
				list.add(topic);
				
				Collections.sort(list, TYPE_COMPARATOR);
			}
			
			cache.add(FQN_FORUM, forumId, list);
		
			Map m = (Map)cache.get(FQN, RELATION);
			
			if (m == null) {
				m = new HashMap();
			}
			
			m.put(new Integer(topic.getId()), new Integer(forumId));
			
			cache.add(FQN, RELATION, m);
		}
	}
	
	/**
	 * Updates a cached topic
	 * 
	 * @param topic The topic to update
	 */
	public static void updateTopic(Topic topic)
	{  
		if (SystemGlobals.getBoolValue(ConfigKeys.TOPIC_CACHE_ENABLED)) {
			synchronized (FQN_FORUM) {
				String forumId = Integer.toString(topic.getForumId());
				List l = (List)cache.get(FQN_FORUM, forumId);
				if (l != null) {
					int index = l.indexOf(topic);
					if (index > -1) {
						l.set(index, topic);
						cache.add(FQN_FORUM, forumId, l);
					}
				}
			}
			//add by myself for虚拟总论坛 // 用于更新view数和回复数
			synchronized(ALL_CACHE_TOPICS){
			List allCachedTopics=(LinkedList)cache.get(FQN,ALL_CACHE_TOPICS);
			if(allCachedTopics!=null){
				int index=allCachedTopics.indexOf(topic);
				if(index>-1){
					allCachedTopics.set(index, topic);
				}
				cache.add(FQN, ALL_CACHE_TOPICS,allCachedTopics);
			}
			}
			
			//add by myself for酷帖
			synchronized(KU_TOPICS){
				List allCachedKuTopics=(LinkedList)cache.get(FQN,KU_TOPICS);
				if(allCachedKuTopics!=null){
					int index=allCachedKuTopics.indexOf(topic);
					if(index>-1){
						allCachedKuTopics.set(index, topic);
					}
					cache.add(FQN, KU_TOPICS,allCachedKuTopics);
				}
				}
			//for 最新帖子
			synchronized(RECENT){
				List recentTopics=(LinkedList)cache.get(FQN, RECENT);
				if(recentTopics!=null){
					int index=recentTopics.indexOf(topic);
					if(index>-1){
						recentTopics.set(index, topic);
						cache.add(FQN, RECENT,recentTopics);
					}
				}
				
			}
			//for 最新发表
			synchronized(TOPIC_BY_PUBLISH_TIME_CACHE){
				List cachedByPublishTimeTopics=(LinkedList)cache.get(FQN,TOPIC_BY_PUBLISH_TIME_CACHE);
				if(cachedByPublishTimeTopics!=null){
					int index=cachedByPublishTimeTopics.indexOf(topic);
					if(index>-1){
						cachedByPublishTimeTopics.set(index, topic);
						cache.add(FQN, TOPIC_BY_PUBLISH_TIME_CACHE,cachedByPublishTimeTopics);
					}
				}
				
			}
			
		}
	}
	
	/**
	 * Gets a cached topic.
	 * 
	 * @param t The topic to try to get from the cache. The instance
	 * passed as argument should have ae least the topicId and forumId set
	 * @return The topic instance, if found, or <code>null</code> otherwise. 
	 */
	public static Topic getTopic(Topic t)
	{
		if (!SystemGlobals.getBoolValue(ConfigKeys.TOPIC_CACHE_ENABLED)) {
			return null;
		}
		
		if (t.getForumId() == 0) {
			Map m = (Map)cache.get(FQN, RELATION);
			
			if (m != null) {
				Integer forumId = (Integer)m.get(new Integer(t.getId()));
				
				if (forumId != null) {
					t.setForumId(forumId.intValue());
				}
			}
			
			if (t.getForumId() == 0) {
				return null;
			}
		}
		
		List l = (List)cache.get(FQN_FORUM, Integer.toString(t.getForumId()));
		
		int index = -1;
		
		if (l != null) {
			index = l.indexOf(t);
		}
		
		return (index == -1 ? null : (Topic)l.get(index));
	}
	
	/**
	 * Checks if a topic is cached
	 * 
	 * @param topic The topic to verify
	 * @return <code>true</code> if the topic is cached, or <code>false</code> if not.
	 */
	public static boolean isTopicCached(Topic topic)
	{
		if (!SystemGlobals.getBoolValue(ConfigKeys.TOPIC_CACHE_ENABLED)) {
			return false;
		}
		
		String forumId = Integer.toString(topic.getForumId());
		List list = (List)cache.get(FQN_FORUM, forumId);
		
		return list == null ? false : list.contains(topic);
	}
	
	/**
	 * Get all cached topics related to a forum. 
	 * 
	 * @param forumid The forum id 
	 * @return <code>ArrayList</code> with the topics.
	 */
	public static List getTopics(int forumid,int start)
	{   int topicPerPage = SystemGlobals.getIntValue(ConfigKeys.TOPICS_PER_PAGE);
		if (SystemGlobals.getBoolValue(ConfigKeys.TOPIC_CACHE_ENABLED)) {
			synchronized (FQN_FORUM) {
				List returnList = (List)cache.get(FQN_FORUM, Integer.toString(forumid));

				if (returnList == null) {
					return new ArrayList();
				}
				 if(start>returnList.size()-1){
				    	return new LinkedList();
				    }
				int endIndex=start+topicPerPage;
				if(endIndex>returnList.size())
				endIndex=returnList.size();
				return new ArrayList(returnList.subList(start, endIndex));
			}
		}
		
		return new ArrayList();
	}
	
	
	
	/*****************************************************************************
	 * 
	 * 
	 * added for alltopic cache
	 * 
	 * 
	 *****************************************************************************/
	
	
	
/*
 * 直接在每次系统初始化，删除topic和增加topic的时候loadTopicsCount();
 * 其他时候都在Cache里面取值，减少数据库访问量；
 * 
 * */
	
	
	public  static int loadTopicsCount() {
		TopicDAO tm = DataAccessDriver.getInstance().newTopicDAO();
		int count=tm.countAllTopics();
		synchronized(TOPICS_COUNT){
		cache.add(FQN, TOPICS_COUNT, new Integer(count));
		}

		return count;
	}


	public static Integer getTopicsCount() {
		Integer topicCount=(Integer)cache.get(FQN, TOPICS_COUNT);
		if(topicCount==null) return loadTopicsCount();
		else return topicCount;
	}
	public  static void pushTopicToCache(Topic topic)
	{   
		if (SystemGlobals.getBoolValue(ConfigKeys.TOPIC_CACHE_ENABLED)) {
			synchronized (ALL_CACHE_TOPICS){
				
		   	LinkedList l = (LinkedList)cache.get(FQN, ALL_CACHE_TOPICS);
			if (l == null || l.size() == 0) {
				l = new LinkedList(loadAllTopicsForCache());
			}else {
				boolean contains = l.contains(topic);
				int cacheSize=SystemGlobals.getIntValue(ConfigKeys.TOTAL_TOPICS_CHCHE_SIZE);
//				int totalTopicCachePage=SystemGlobals.getIntValue(ConfigKeys.TOTAL_TOPICS_CACHE_PAGE);
//				int topicPerPage = SystemGlobals.getIntValue(ConfigKeys.TOPICS_PER_PAGE);
				// If the cache is full, remove the eldest element
				if (!contains && l.size() + 1 > cacheSize) {
					l.removeLast();
				}
				else if (contains) {
					l.remove(topic);
				}
				
				l.addFirst(topic);
				
				Collections.sort(l, TYPE_COMPARATOR);
			}
 			cache.add(FQN, ALL_CACHE_TOPICS, l);
			}
		}
		loadTopicsCount();//避免因为topic提交过多，count出错，排序出错
	}
	
	public static void clearAllTopicsCache(){
		synchronized (ALL_CACHE_TOPICS) {
			cache.add(FQN, ALL_CACHE_TOPICS, new LinkedList());
		}
	}
	public static List loadAllTopicsForCache() {

		TopicDAO tm = DataAccessDriver.getInstance().newTopicDAO();
		List l = null;
     	int cacheSize=SystemGlobals.getIntValue(ConfigKeys.TOTAL_TOPICS_CHCHE_SIZE);
     	l = tm.selectAllTopicsByReplyTimeByLimit(0,cacheSize);
		synchronized (ALL_CACHE_TOPICS) {
			cache.add(FQN, ALL_CACHE_TOPICS, new LinkedList(l));
		}
		return l;
	}

	public static List getAllCacheTopics() {
		List l = (List) cache.get(FQN, ALL_CACHE_TOPICS);

		if (l == null || l.size() == 0
				|| !SystemGlobals.getBoolValue(ConfigKeys.TOPIC_CACHE_ENABLED)) {
			l = loadAllTopicsForCache();
		}

		return new ArrayList(l);
	}

	public static List getCacheTopicsByLimit(int start,int limit) {
		List cachedTopics=getAllCacheTopics();
		int endIndex=start+limit;
	    if(start>cachedTopics.size()-1){
	    	return new LinkedList();
	    }
		if(endIndex>cachedTopics.size())
			endIndex=cachedTopics.size();
		return cachedTopics.subList(start, endIndex);

	}
	
	public static List getTopicsByLimit(int start,int limit){
		int cacheSize=SystemGlobals.getIntValue(ConfigKeys.TOTAL_TOPICS_CHCHE_SIZE);
		if(start+limit<cacheSize+1){
		return 	getCacheTopicsByLimit(start,limit);
		}
		else{
			 TopicDAO tm = DataAccessDriver.getInstance().newTopicDAO();
	    	   return tm.selectAllTopicsByReplyTimeByLimit(start, limit);
		}
		
	}

	
	
	
	
	
	
	
	
	//获取酷帖:
	public  static int loadKuTopicsCount(){
		TopicDAO tm = DataAccessDriver.getInstance().newTopicDAO();
		int count=tm.countKuTopics();
		cache.add(FQN, Ku_TOPICS_COUNT, new Integer(count));
		return count;
		
	}
	public static void clearCacheForKuTopics(){
		synchronized(KU_TOPICS){
			cache.remove(FQN,KU_TOPICS);
		}
	}
	public static int getKuTopicsCount(){

		Integer topicCount=(Integer)cache.get(FQN, Ku_TOPICS_COUNT);
		if(topicCount==null) return loadKuTopicsCount();
		else return topicCount;
	}
	public static List loadKuTopics(){

		TopicDAO tm = DataAccessDriver.getInstance().newTopicDAO();
		  int cacheSize=SystemGlobals.getIntValue(ConfigKeys.KUTOPIC_CACHE_SIZE);
 
		List l = tm.selectKuTopicsByLimit(0, cacheSize);
        synchronized(KU_TOPICS){
		cache.add(FQN, KU_TOPICS, new LinkedList(l));
		}
        synchronized(Ku_TOPICS_COUNT){
        	cache.add(FQN, Ku_TOPICS_COUNT, new ArrayList(l).size());
        }
		return l;
	}
	
	public static List getAllCachedKuTopics(){
		List l = (List) cache.get(FQN, KU_TOPICS);

		if (l == null || l.size() == 0
				|| !SystemGlobals.getBoolValue(ConfigKeys.TOPIC_CACHE_ENABLED)) {
			l = loadKuTopics();
		}

		return new ArrayList(l);
	}
	
	public static List getCachedKuTopicsByLimit(int start,int limit){
		List cachedTopics=getAllCachedKuTopics();
	    if(start>cachedTopics.size()-1){
	    	return new LinkedList();
	    }
		int endIndex=start+limit;
		if(endIndex>cachedTopics.size())
			endIndex=cachedTopics.size();
		return cachedTopics.subList(start, endIndex);
	}
	
	public static List getKuTopicsByLimit(int start ,int limit){
		  int cacheSize=SystemGlobals.getIntValue(ConfigKeys.KUTOPIC_CACHE_SIZE);		   
	      if(start+limit<cacheSize+1){
	    	   return getCachedKuTopicsByLimit(start,limit);
	       }else{
	    	   TopicDAO tm = DataAccessDriver.getInstance().newTopicDAO();
	    	   return tm.selectKuTopicsByLimit(start, limit);
	       }	
	}
	public static void pushKuTopicToCache(Topic topic){
		if (SystemGlobals.getBoolValue(ConfigKeys.TOPIC_CACHE_ENABLED)) {
			synchronized (KU_TOPICS){
		   	LinkedList l = (LinkedList)cache.get(FQN, KU_TOPICS);
			if (l == null || l.size() == 0) {
				l = new LinkedList(loadKuTopics());
			}else {
				int cacheSize=SystemGlobals.getIntValue(ConfigKeys.KUTOPIC_CACHE_SIZE);
				boolean contains = l.contains(topic);
//				int totalTopicCachePage=SystemGlobals.getIntValue(ConfigKeys.KUTOPIC_CACHE_PAGE);
//				int topicPerPage = SystemGlobals.getIntValue(ConfigKeys.TOPICS_PER_PAGE);
				// If the cache is full, remove the eldest element
				if (!contains && l.size() + 1 > cacheSize) {
					l.removeLast();
				}
				else if (contains) {
					l.remove(topic);
				}
				
				l.addFirst(topic);
				
			}
 			cache.add(FQN, KU_TOPICS, l);
			}
		}
	}
	
	
	// 最新发表
	// 默认缓存主题大小大于 每页显示主题
	
	public static void clearCacheForTopicsByPublishTime(){
		synchronized(TOPIC_BY_PUBLISH_TIME_CACHE){
			cache.remove(FQN, TOPIC_BY_PUBLISH_TIME_CACHE);
		}
	}
	
	public static void updateTopicInPublishCache(Topic topic){
		synchronized(TOPIC_BY_PUBLISH_TIME_CACHE){
		List cachedByPublishTimeTopics=(LinkedList)cache.get(FQN,TOPIC_BY_PUBLISH_TIME_CACHE);
		if(cachedByPublishTimeTopics!=null){
			int index=cachedByPublishTimeTopics.indexOf(topic);
			if(index>-1){			
				cachedByPublishTimeTopics.set(index, topic);
				cache.add(FQN, TOPIC_BY_PUBLISH_TIME_CACHE,cachedByPublishTimeTopics);
				}
			}
		}
	}
   
   public static void removeTopicInPublishCache(Topic topic){
	   synchronized(TOPIC_BY_PUBLISH_TIME_CACHE){
		   List cachedByPublishTimeTopics=(LinkedList)cache.get(FQN,TOPIC_BY_PUBLISH_TIME_CACHE);
		   if(cachedByPublishTimeTopics!=null){
				int index=cachedByPublishTimeTopics.indexOf(topic);
				if(index>-1){
					int cacheSize = SystemGlobals
					.getIntValue(ConfigKeys.TOPIC_BY_PUBLISH_TIME_CACHE_SIZE);
					TopicDAO tm = DataAccessDriver.getInstance().newTopicDAO();
					List l = tm.selectAllTopicsByTopicTimeLimit(0, cacheSize);	 
					cache.add(FQN, TOPIC_BY_PUBLISH_TIME_CACHE, new LinkedList(l));
				}
				}
	   }
   }
   
	public static  List loadTopicsByPublishTime(int start, int limit) {
		synchronized(TOPIC_BY_PUBLISH_TIME_CACHE){
		TopicDAO tm = DataAccessDriver.getInstance().newTopicDAO();
		List l = null;		
			l = tm.selectAllTopicsByTopicTimeLimit(start, limit);	 
			cache.add(FQN, TOPIC_BY_PUBLISH_TIME_CACHE, new LinkedList(l));
 
		return l;}
	}

	public static List getAllCachedTopicsByPublishTime() {
		List l = (List) cache.get(FQN, TOPIC_BY_PUBLISH_TIME_CACHE);
		
		int cacheSize = SystemGlobals
				.getIntValue(ConfigKeys.TOPIC_BY_PUBLISH_TIME_CACHE_SIZE);
		if (l == null || l.size() == 0
				|| !SystemGlobals.getBoolValue(ConfigKeys.TOPIC_CACHE_ENABLED)) {
			l = loadTopicsByPublishTime(0, cacheSize);
		}
		return new ArrayList(l);
	}
    
	public static int countCacheTopicsByPublishTime(){
		 List l = (List) cache.get(FQN, TOPIC_BY_PUBLISH_TIME_CACHE);
		 if(l!=null){
			 return l.size();
		 }else {
			 int cacheSize = SystemGlobals
				.getIntValue(ConfigKeys.TOPIC_BY_PUBLISH_TIME_CACHE_SIZE);
			 List topics=(List)loadTopicsByPublishTime(0,cacheSize);
			 return topics==null?0:topics.size();}
	}
	
	public static void pushTopicToPublishCache(Topic topic) {
		if (SystemGlobals.getBoolValue(ConfigKeys.TOPIC_CACHE_ENABLED)) {
			synchronized (TOPIC_BY_PUBLISH_TIME_CACHE) {
				LinkedList l = (LinkedList) cache.get(FQN,
						TOPIC_BY_PUBLISH_TIME_CACHE);
				int cacheSize = SystemGlobals
						.getIntValue(ConfigKeys.TOPIC_BY_PUBLISH_TIME_CACHE_SIZE);
				if (l == null || l.size() == 0) {
					l = new LinkedList(loadTopicsByPublishTime(0, cacheSize));
				} else {

					boolean contains = l.contains(topic);
					if (!contains && l.size() + 1 > cacheSize) {
						l.removeLast();
					} else if (contains) {
						l.remove(topic);
					}

					l.addFirst(topic);
//					Collections.sort(l, TYPE_COMPARATOR);

				}
				cache.add(FQN, TOPIC_BY_PUBLISH_TIME_CACHE, l);
			}
		}
	}

	public static List getAllCachedTopicsByPublishTimeByLimit(int start, int limit) {
		int cacheSize = SystemGlobals
				.getIntValue(ConfigKeys.TOPIC_BY_PUBLISH_TIME_CACHE_SIZE);
		List cachedTopics = getAllCachedTopicsByPublishTime();
		int endIndex = start + limit;
		if (start > cachedTopics.size() - 1) {
			return new LinkedList();
		}
		if (endIndex > cachedTopics.size())
			endIndex = cachedTopics.size();
		return cachedTopics.subList(start, endIndex);

	}
	
	
	
 
}

